package com.peng;

import com.design_pattern.observer.Event;
import com.design_pattern.observer.TankObserver;
import com.design_pattern.stragery.DeafultFireStraery;
import com.design_pattern.stragery.FireStragery;

import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Tank extends GameObject {
    public static int SPEED = Integer.parseInt(PropertiesManager.getValue("TANK_SPEED"));
    public Dir dir;

    public static final int WIDTH = ResourceManager.tankD.getWidth();
    public static final int HEIGHT = ResourceManager.tankD.getWidth();

    private boolean moving = false;
    private boolean live = true;
    private Group group = Group.BAD;
    private Random random = new Random();
    private Rectangle rectangle;
    private int beforeX;
    private int beforeY;

    private List<TankObserver> observerList = new ArrayList<>();


    public Tank() {
        this.dir = Dir.D;
    }

    public Tank(int x, int y, Group group, boolean isMoving) {
        this.x = x;
        this.y = y;
        this.beforeX = x;
        this.beforeY = y;
        this.group = group;
        this.moving = isMoving;
        width = ResourceManager.tankD.getWidth();
        height = ResourceManager.tankD.getWidth();
        this.rectangle = new Rectangle(x, y, width, height);
        this.dir = Dir.D;
        observerList.add(new TankObserver());
        GameModel.getInstance().add(this);
    }

    public Rectangle getRectangle() {
        return rectangle;
    }

    public void setRectangle(Rectangle rectangle) {
        this.rectangle = rectangle;
    }


    @Override
    public void paint(Graphics g) {
        if (!isLive()) {
            GameModel.getInstance().remove(this);
            return;
        }
        move();
        switch (dir) {
            case U:
                g.drawImage(ResourceManager.tankU, x, y, null);
                break;
            case D:
                g.drawImage(ResourceManager.tankD, x, y, null);
                break;
            case L:
                g.drawImage(ResourceManager.tankL, x, y, null);
                break;
            case R:
                g.drawImage(ResourceManager.tankR, x, y, null);
                break;
            case LU:
                g.drawImage(ResourceManager.tankLU, x, y, null);
                break;
            case RU:
                g.drawImage(ResourceManager.tankRU, x, y, null);
                break;
            case RD:
                g.drawImage(ResourceManager.tankRD, x, y, null);
                break;
            case LD:
                g.drawImage(ResourceManager.tankLD, x, y, null);
                break;
        }

        this.rectangle.x = x;
        this.rectangle.y = y;

    }


    public void move() {
        if (moving) {
            beforeX = x;
            beforeY = y;
            switch (dir) {
                case U:
                    y -= SPEED;
                    break;
                case D:
                    y += SPEED;
                    break;
                case L:
                    x -= SPEED;
                    break;
                case R:
                    x += SPEED;
                    break;
                case LU:
                    x -= SPEED;
                    y -= SPEED;
                    break;
                case RU:
                    x += SPEED;
                    y -= SPEED;
                    break;
                case RD:
                    x += SPEED;
                    y += SPEED;
                    break;
                case LD:
                    x -= SPEED;
                    y += SPEED;
                    break;
            }

            if (random.nextInt(100) > 95 && group == Group.BAD) randomDir();

            checkBound();

        }
        //随机发射，只让敌方阵容自动攻击
        if (random.nextInt(10) > 5 && group == Group.BAD) {
            fire(DeafultFireStraery.getInstance());
        }


    }

    private void randomDir() {
        int randDirNum = random.nextInt(Dir.values().length);
        for (Dir value : Dir.values()) {
            if (value.ordinal() == randDirNum) {
                dir = value;
                return;
            }
        }

    }

    private void checkBound() {
        if (x > TankFrame.GAME_WIDTH - width) {
            x = TankFrame.GAME_WIDTH - height;
        }
        if (x < 0) {
            x = 0;
        }
        if (y > TankFrame.GAME_HEIGHT - height) {
            y = TankFrame.GAME_HEIGHT - height;
        }
        if (y < 28) {
            y = 28;
        }
    }

    public boolean isMoving() {
        return moving;
    }

    public void setMoving(boolean moving) {
        this.moving = moving;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public Dir getDir() {
        return dir;
    }

    public void setDir(Dir dir) {
        this.dir = dir;
    }

    public void fire(FireStragery fireStragery) {
        fireStragery.fire(this);

    }

    public Group getGroup() {
        return group;
    }

    public void setGroup(Group group) {
        this.group = group;
    }

    public boolean isLive() {
        return live;
    }

    public void setLive(boolean live) {
        this.live = live;
    }


    public void die() {
        this.live = false;
    }



    @Override
    public String toString() {
        return "Tank{" +
                "live=" + live + this.hashCode()
                +
                '}';
    }

    public void stop() {
        this.moving = false;
    }

    /**
     * 反方向
     */
    public void reverseDir() {
        //改变方向
        switch (dir) {
            case U:
                this.setDir(Dir.D);
                break;
            case D:
                this.setDir(Dir.U);
                break;
            case L:
                this.setDir(Dir.R);
                break;
            case R:
                this.setDir(Dir.L);
                break;
            case LD:
                this.setDir(Dir.RU);
                break;
            case RU:
                this.setDir(Dir.LD);
                break;
            case LU:
                this.setDir(Dir.RD);
                break;
            case RD:
                this.setDir(Dir.LU);
                break;

        }
    }

    public void back() {
        this.x = beforeX;
        this.y = beforeY;
    }


    public void toNoticeFire() {
        for (TankObserver observer : observerList) {
            observer.doSomething(new Event<>(GameModel.getInstance().getMainTank()));
        }
    }
}
